package com.newtouch.bxzs.business.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.newtouch.bxzs.business.enclosure.service.AttachmentService;
import com.newtouch.bxzs.business.message.mapper.SysParameterMapper;
import com.newtouch.bxzs.business.message.service.AnnouncementService;
import com.newtouch.bxzs.business.product.controller.ProductController;
import com.newtouch.bxzs.business.product.mapper.*;
import com.newtouch.bxzs.business.product.model.*;
import com.newtouch.bxzs.business.product.service.*;
import com.newtouch.bxzs.common.base.BaseErrorEnum;
import com.newtouch.bxzs.common.base.BaseException;
import com.newtouch.bxzs.common.base.em.SystemParamsEnum;
import com.newtouch.bxzs.common.base.model.*;
import com.newtouch.bxzs.common.base.model.vo.EnclosureVO;
import com.newtouch.bxzs.common.base.util.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Pattern;

/**
 * 建议书的实现类
 * <p>
 * <b>History:</b>
 * <table border="1">
 * <tr>
 * <th>Date</th>
 * <th>Operator</th>
 * <th>Memo</th>
 * </tr>
 * <tr>
 * <td>2021/1/11 16:25</td>
 * <td>lanwei</td>
 * <td>Create</td>
 * </tr>
 * </table>
 *
 * @author lanwei
 * @version 1.0.0
 * @since 1.0.0
 */
@Service
public class RecommendationServiceImpl implements RecommendationService {

    @Resource
    private RecommendationMapper recommendationMapper;

    @Autowired
    private AttachmentService attachmentService;

    @Resource
    private ProductMapper productMapper;

    @Resource
    private AdditionalMapper additionalMapper;

    @Autowired
    private ProductFeignClient productFeignClient;

    @Resource
    private ProductService productService;

    @Resource
    private RecommendationSafeGuardInsuranceMapMapper recommendationSafeGuardInsuranceMapMapper;

    @Resource
    private RecommendationSafeGuardInterestsFormulaMapMapper recommendationSafeGuardInterestsFormulaMapMapper;

    @Autowired
    private AnnouncementService announcementService;

    @Autowired
    private RedisUtils redisUtils;

    @Resource
    private SysParameterMapper sysParameterMapper;

    /**
     * 效验年龄
     */
    private final static String NUMBER_CHECK = "[0-9]*";

    /**
     * 特殊的保险期间
     */
    private final static String POLICY_PERIOD = "终生";

    /**
     * 一年的天数
     */
    private final static Integer ONE_YEAR = 365;

    /**
     * 客户标签的其他类型
     */
    private final static Integer OTHER_LABEL = 99;

    /**
     * 默认产品推荐分页参数
     */
    private final static Integer limit = 99999;

    /**
     * 默认产品推荐分页参数
     */
    private final static Integer currentPage = 1;

    /**
     * 静态变量：系统日志
     */
    private static final Log logger = LogFactory.getLog(ProductController.class);

    /**
     * (non-Javadoc)
     * <p>
     * com.newtouch.bxzs.business.product.service.RecommendationService#
     * getRecommendationDetail(java.lang.String)
     */
    @Override
    public RecommendationDetailBO getRecommendationDetail(String recommendationId) {
        /* 查看建议书详情 */
        Recommendation recommendation = recommendationMapper.selectById(recommendationId);
        if (BeanUtil.isEmpty(recommendation)) {
            logger.info("id错误");
            throw new BaseException(BaseErrorEnum.REQUEST_PARAMETER_ERROR);
        }
        RecommendationDetailBO recommendationDetailBO = new RecommendationDetailBO();
        BeanUtil.copyProperties(recommendation, recommendationDetailBO);
        QueryWrapper<Product> query = new QueryWrapper<>();
        /* 获取产品id,用户查询产品附件 */
        query.eq("PRODUCT_CODE", recommendationDetailBO.getProductCode());
        /* 获取产品分类 */
        recommendationDetailBO.setProductType(productMapper.selectOne(query).getProductType());
        /* 获取附件 */
        HashMap<String, List<String>> result = attachmentService
                .getEnclosureList(new EnclosureVO(productMapper.selectOne(query).getProductId(), null));
        if (result != null) {
            recommendationDetailBO.setAttachmentList(result);
        }
        /* 包装附加险数据 */
        List<InsuranceBO> additionalList = additionalMapper.getInsuranceBOList(recommendationId);
        /* 将主险信息加入列表 */
        InsuranceBO bo = new InsuranceBO();
        bo.setProductCode(recommendation.getProductCode());
        bo.setProductName(recommendation.getProductName());
        bo.setPolicyAmount(recommendation.getPolicyAmount());
        bo.setPolicyPremium(recommendation.getPolicyPremium());
        additionalList.add(0, bo);
        recommendationDetailBO.setAdditionalList(additionalList);
        String policyPeriod;
        for (InsuranceBO insuranceBO : additionalList) {
            policyPeriod = recommendation.getPolicyPeriod();
            if (POLICY_PERIOD.equals(recommendation.getPolicyPeriod())) {
                policyPeriod = "100";
            }
            insuranceBO.setPolicyPeriod(policyPeriod);
            insuranceBO.setPaymentPeriod(recommendation.getPolicyPayPeriod());
        }
        /* 设置保障集合 */
        /* 实例化一个保障集合 */
        List<RecommendationSafeGuardInterestsMapBO> recommendationSafeGuardInterestsMapBOS = new ArrayList<>();
        /* 计算保障集合名目个数，用于判断实例化个数 */
        List<RecommendationSafeGuardInterestsMapBO> titleList = recommendationSafeGuardInsuranceMapMapper.getSafeGuardInsuranceTitleList(recommendationId);
        /* 包装所有保障集合 */
        for (RecommendationSafeGuardInterestsMapBO safeGuardInsuranceMapBO : titleList) {
            RecommendationSafeGuardInterestsMapBO recommendationSafeGuardInterestsMapBO = new RecommendationSafeGuardInterestsMapBO();
            /* 设置详细内容 */
            recommendationSafeGuardInterestsMapBO.setSafeGuardInterestsDetailedSubContent(safeGuardInsuranceMapBO.getSafeGuardInterestsDetailedSubContent());
            /* 设置名目 */
            recommendationSafeGuardInterestsMapBO.setSafeGuardInterestsTitle(safeGuardInsuranceMapBO.getSafeGuardInterestsTitle());
            /* 根据名目查询和建议书id查询子内容和内容的集合 */
            recommendationSafeGuardInterestsMapBO.setRecommendationSafeGuardInterestsMapSubBOList(recommendationSafeGuardInsuranceMapMapper.getSafeGuardInsuranceSubList(recommendationId, safeGuardInsuranceMapBO.getSafeGuardInterestsTitle()));
            /* 加入集合 */
            recommendationSafeGuardInterestsMapBOS.add(recommendationSafeGuardInterestsMapBO);
        }
        recommendationDetailBO.setRecommendationSafeGuardInsuranceMapList(recommendationSafeGuardInterestsMapBOS);
        /* 设置利益演示集合 */
        QueryWrapper<RecommendationSafeGuardInterestsFormulaMap> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("RECOMMENDATION_ID", recommendationId);
        /* 包装结构 */
        Map<String, List<RecommendationSafeGuardInterestsFormulaMapBO>> hashMap = new LinkedHashMap<>();
        for (RecommendationSafeGuardInterestsFormulaMapBO formulaMapBO : EntityToBeanUtils.copyBean(recommendationSafeGuardInterestsFormulaMapMapper.selectList(queryWrapper), RecommendationSafeGuardInterestsFormulaMapBO.class)) {
            /* map中存在此id，将数据存放当前key的map中 */
            if (hashMap.containsKey(formulaMapBO.getSafeGuardInterestsTypeName())) {
                hashMap.get(formulaMapBO.getSafeGuardInterestsTypeName()).add(formulaMapBO);
            } else {// map中不存在，新建key，用来存放数据
                List<RecommendationSafeGuardInterestsFormulaMapBO> formulaMapList = new ArrayList<>();
                formulaMapList.add(formulaMapBO);
                hashMap.put(formulaMapBO.getSafeGuardInterestsTypeName(), formulaMapList);
            }
        }
        recommendationDetailBO.setSafeGuardInterestsFormulaMapList(hashMap);
        return recommendationDetailBO;
    }

    /**
     * (non-Javadoc)
     * <p>
     * com.newtouch.bxzs.business.product.service.RecommendationService#
     * getRecommendationList(com.newtouch.bxzs.business.product.model.
     * RecommendationVO)
     */
    @Override
    public RecommendationPagingListBO getRecommendationList(RecommendationVO recommendationVO) {
        if (BeanUtil.isEmpty(recommendationVO.getCurrentPage()) || recommendationVO.getCurrentPage() < 1) {
            logger.info("查询列表失败");
            throw new BaseException(BaseErrorEnum.REQUEST_PARAMETER_ERROR);
        }
        int recommendationYear = Integer.parseInt(announcementService.getParameterValueRedis(SystemParamsEnum.RECOMMENDATION_MIN_SELECT_YEAR.getCode()));
        /* 效验时间 */
        if (recommendationVO.getEndTime() != null) {
            if (recommendationVO.getStartTime() != null) {
                if (recommendationVO.getEndTime().before(recommendationVO.getStartTime())) {
                    logger.info("时间条件设置不合规范");
                    throw new BaseException(BaseErrorEnum.REQUEST_PARAMETER_ERROR.getResultCode(), BaseErrorEnum.REQUEST_PARAMETER_ERROR.getResultMsg() + ",时间条件设置不合规范");
                }
            }
            if (recommendationVO.getEndTime().before(DateUtil.offsetDay(new Date(), -ONE_YEAR * recommendationYear))) {
                logger.info("时间条件设置不合规范");
                throw new BaseException(BaseErrorEnum.REQUEST_PARAMETER_ERROR.getResultCode(), BaseErrorEnum.REQUEST_PARAMETER_ERROR.getResultMsg() + ",只能查询到从当前日期往前" + recommendationYear + "年内的建议书信息");
            }
        }
        /* 根据传进来的页码计算limit的开始值和结束值 */
        int startPage = ((recommendationVO.getCurrentPage() - 1) * 10);
        int endPage = startPage + 10;
        if (recommendationVO.getEndTime() != null) {
            recommendationVO.setEndTime(DateUtil.offsetDay(recommendationVO.getEndTime(), 1));
        }
        /* 查询列表 */
        List<RecommendationListBO> recommendationList = recommendationMapper.getRecommendationList(
                recommendationVO.getProductType(), recommendationVO.getProductName(), recommendationVO.getInsuredName(),
                recommendationVO.getStartTime(), recommendationVO.getEndTime(), recommendationYear, recommendationVO.getRecommendationName());
        Map<String, List<RecommendationListBO>> hashMap = new LinkedHashMap<>();
        /* 包装结构 */
        for (RecommendationListBO recommendationListBO : recommendationList) {
            /* map中存在此id，将数据存放当前key的map中 */
            if (hashMap.containsKey(recommendationListBO.getInsurederName() + "," + recommendationListBO.getInsurederCertificateType() + "," + recommendationListBO.getInsurederCertificateNumber())) {
                //判断是不是同一个人
                hashMap.get(recommendationListBO.getInsurederName() + "," + recommendationListBO.getInsurederCertificateType() + "," + recommendationListBO.getInsurederCertificateNumber()).add(recommendationListBO);
            } else {// map中不存在，新建key，用来存放数据
                List<RecommendationListBO> recommendationListBOList = new ArrayList<>();
                recommendationListBOList.add(recommendationListBO);
                hashMap.put(recommendationListBO.getInsurederName() + "," + recommendationListBO.getInsurederCertificateType() + "," + recommendationListBO.getInsurederCertificateNumber(), recommendationListBOList);
            }
        }
        /* 分页 */
        List<String> hashKeyList = new ArrayList<>();
        for (Map.Entry<String, List<RecommendationListBO>> stringListEntry : hashMap.entrySet()) {
            hashKeyList.add(stringListEntry.getKey());
        }
        List<String> list;
        if (startPage > hashKeyList.size()) {
            return null;
        } else {
            if (endPage < hashKeyList.size()) {
                list = hashKeyList.subList(startPage, endPage);
            } else {
                list = hashKeyList.subList(startPage, hashKeyList.size());
            }
        }
        List<Map<String, List<RecommendationListBO>>> hashList = new ArrayList<>();
        Map<String, List<RecommendationListBO>> recommendationHashMap = new LinkedHashMap<>();
        for (String s : list) {
            for (Map.Entry<String, List<RecommendationListBO>> stringListEntry : hashMap.entrySet()) {
                String key = stringListEntry.getKey();
                if (Objects.equals(s, key)) {
                    recommendationHashMap.put(key, hashMap.get(key));
                }
            }
        }
        //修改map的key值
        Iterator<Map.Entry<String, List<RecommendationListBO>>> iterator = recommendationHashMap.entrySet().iterator();
        Map.Entry<String, List<RecommendationListBO>> entry;
        while (iterator.hasNext()) {
            entry = iterator.next();
            // 往newMap中放入新的Entry
            HashMap<String, List<RecommendationListBO>> newMap = new LinkedHashMap<>();
            newMap.put(entry.getKey().split(",")[0], entry.getValue());
            hashList.add(newMap);
        }
        RecommendationPagingListBO recommendationPagingListBO = new RecommendationPagingListBO();
        recommendationPagingListBO.setHashMap(hashList);
        /* 获取key的长度 */
        recommendationPagingListBO.setTotal(recommendationMapper.getRecommendationLength(recommendationVO.getProductType(), recommendationVO.getProductName(), recommendationVO.getInsuredName(),
                recommendationVO.getStartTime(), recommendationVO.getEndTime(), recommendationYear, recommendationVO.getRecommendationName()));
        return recommendationPagingListBO;
    }

    /**
     * (non-Javadoc)
     * <p>
     * com.newtouch.bxzs.business.product.service.RecommendationService#
     * compareRecommendation(java.lang.List)
     */
    @Override
    public List<RecommendationCompareBO> compareRecommendation(List<String> recommendationIds) {
        /* 建议书对比最大数 */
        int maxCompareCount = 5;
        if (CollectionUtil.isEmpty(recommendationIds) || recommendationIds.size() > maxCompareCount) {
            throw new BaseException(BaseErrorEnum.REQUEST_DATA_NULL.getResultCode(), BaseErrorEnum.REQUEST_DATA_NULL.getResultMsg() + "或集合大于5");
        }
        /* 查询建议书列表 */
        QueryWrapper<Recommendation> query = new QueryWrapper<>();
        query.in("RECOMMENDATION_ID", recommendationIds);
        List<Recommendation> recommendationList = recommendationMapper.selectList(query);
        /* 判断id是否都有效 */
        if (recommendationIds.size() > recommendationList.size()) {
            logger.info("传入的建议书id集合中存在无效");
            throw new BaseException("-1", "传入的建议书id集合中存在无效");
        }
        if (CollectionUtil.isEmpty(recommendationList)) {
            logger.info("建议书集合为空");
            throw new BaseException(BaseErrorEnum.REQUEST_DATA_NULL);
        }
        List<RecommendationCompareBO> recommendationCompareBO = EntityToBeanUtils.copyBean(recommendationList,
                RecommendationCompareBO.class);
        /* 获取产品id,用户查询产品附件 */
        /* 数据量不大，用循环查询产品分类 */
        for (RecommendationCompareBO bo : recommendationCompareBO) {
            QueryWrapper<Product> query2 = new QueryWrapper<>();
            query2.eq("PRODUCT_CODE", bo.getProductCode());
            Product product = productMapper.selectOne(query2);
            /* 如果建议书对应产品编码不存在所属产品，则不赋值 */
            if (!BeanUtil.isEmpty(product)) {
                bo.setProductType(product.getProductType());
                bo.setProductPaymentMethod(product.getProductPaymentMethod());
            }
        }
        /* 效验传入的id是否属于同一被保人和同一产品类型 */
        for (int i = 0; i < recommendationCompareBO.size(); i++) {
            /* 当某些产品被删除时 */
            if (recommendationCompareBO.size() > i + 1) {
                if (BeanUtil.isEmpty(recommendationCompareBO.get(i).getProductType()) && BeanUtil.isEmpty(recommendationCompareBO.get(i + 1).getProductType())) {
                    logger.info("传入的建议书集合中某一产品不存在分类");
                    throw new BaseException("-1", "传入的建议书集合中某一产品不存在分类");
                }
                if (!Objects.equals(recommendationCompareBO.get(i).getInsurederName(),
                        recommendationCompareBO.get(i + 1).getInsurederName())
                        || !recommendationCompareBO.get(i).getProductType()
                        .equals(recommendationCompareBO.get(i + 1).getProductType()) ||
                        !recommendationCompareBO.get(i).getInsurederCertificateNum()
                                .equals(recommendationCompareBO.get(i + 1).getInsurederCertificateNum()) ||
                        !recommendationCompareBO.get(i).getInsurederCertificateType()
                                .equals(recommendationCompareBO.get(i + 1).getInsurederCertificateType())) {
                    logger.info("建议书不属于同一被保人或产品类型不一致");
                    throw new BaseException("-1", "建议书不属于同一被保人或产品类型不一致");
                }
            }
        }
        /* 由于数据量最多五条，循环获取附件集合 */
        /* 设置保障集合 */
        /* 实例化一个保障集合 */
        for (RecommendationCompareBO compareBO : recommendationCompareBO) {
            List<RecommendationSafeGuardInterestsMapBO> recommendationSafeGuardInterestsMapBOS = new ArrayList<>();
            QueryWrapper<RecommendationSafeGuardInterestsMap> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("RECOMMENDATION_ID", compareBO.getRecommendationId());
            /* 计算保障集合名目个数，用于判断实例化个数 */
            List<RecommendationSafeGuardInterestsMapBO> titleList = recommendationSafeGuardInsuranceMapMapper.getSafeGuardInsuranceTitleList(compareBO.getRecommendationId());
            /* 包装所有保障集合 */
            for (RecommendationSafeGuardInterestsMapBO safeGuardInsuranceMapBO : titleList) {
                RecommendationSafeGuardInterestsMapBO recommendationSafeGuardInterestsMapBO = new RecommendationSafeGuardInterestsMapBO();
                /* 设置详细内容 */
                recommendationSafeGuardInterestsMapBO.setSafeGuardInterestsDetailedSubContent(safeGuardInsuranceMapBO.getSafeGuardInterestsDetailedSubContent());
                /* 设置名目 */
                recommendationSafeGuardInterestsMapBO.setSafeGuardInterestsTitle(safeGuardInsuranceMapBO.getSafeGuardInterestsTitle());
                /* 根据名目查询和建议书id查询子内容和内容的集合 */
                recommendationSafeGuardInterestsMapBO.setRecommendationSafeGuardInterestsMapSubBOList(recommendationSafeGuardInsuranceMapMapper.getSafeGuardInsuranceSubList(compareBO.getRecommendationId(), safeGuardInsuranceMapBO.getSafeGuardInterestsTitle()));
                /* 加入集合 */
                recommendationSafeGuardInterestsMapBOS.add(recommendationSafeGuardInterestsMapBO);
            }
            compareBO.setRecommendationSafeGuardInsuranceMapList(recommendationSafeGuardInterestsMapBOS);
        }
        return recommendationCompareBO;
    }

    /**
     * (non-Javadoc)
     * <p>
     * com.newtouch.bxzs.business.product.service.RecommendationService#
     * modifyRecommendation(com.newtouch.bxzs.business.product.model.
     * ModifyRecommendationVO)
     */
    @Override
    public String modifyRecommendation(ModifyRecommendationVO modifyRecommendationVO) {
        /* 判断传入数据是否合格 */
        if (modifyRecommendationVO == null) {
            logger.info("新增失败");
            throw new BaseException(BaseErrorEnum.REQUEST_DATA_NULL);
        }
        /* 校验证件类型和证件号 */
        CheckCertificateTypeUtil.checkCertificate(modifyRecommendationVO.getInsurederCertificateType(), modifyRecommendationVO.getInsurederCertificateNum());
        /* 校验VO */
        Assert.isTrue(!BeanUtil.isEmpty(modifyRecommendationVO.getInsuredAge()), "被保人年龄未填");
        Assert.isTrue(!StringUtils.isEmpty(modifyRecommendationVO.getInsurederName()), "被保人姓名未填");
        Assert.isTrue(!StringUtils.isEmpty(modifyRecommendationVO.getInsuredSex()), "被保人性别未填");
        Assert.isTrue(!BeanUtil.isEmpty(modifyRecommendationVO.getPolicyAmount()), "保额未填");
        Assert.isTrue(!StringUtils.isEmpty(modifyRecommendationVO.getPolicyPayPeriod()), "缴费期未填");
        Assert.isTrue(!StringUtils.isEmpty(modifyRecommendationVO.getPolicyPeriod()), "保障期未填");
        Assert.isTrue(!BeanUtil.isEmpty(modifyRecommendationVO.getPolicyPremium()), "保费未填");
        Assert.isTrue(!StringUtils.isEmpty(modifyRecommendationVO.getProductCode()), "产品编号未填");
        Assert.isTrue(!StringUtils.isEmpty(modifyRecommendationVO.getProductName()), "产品名称未填");
        Assert.isTrue(!StringUtils.isEmpty(modifyRecommendationVO.getInsurederCertificateNum()), "被保人证件号未填");
        Assert.isTrue(!StringUtils.isEmpty(modifyRecommendationVO.getInsurederCertificateType()), "被保人证件类型未填");
        Assert.isTrue(!StringUtils.isEmpty(modifyRecommendationVO.getFirstYearTotal()), "首年保费未填");
        if (CollectionUtil.isEmpty(modifyRecommendationVO.getSafeGuardInterestsFormulaMapList())
                || CollectionUtil.isEmpty(modifyRecommendationVO.getRecommendationSafeGuardInsuranceMapList())) {
            logger.info("未传入保障集合或者未传入利益演示集合");
            throw new BaseException(BaseErrorEnum.REQUIRED_ITEM_NULL.getResultCode(), BaseErrorEnum.REQUIRED_ITEM_NULL.getResultMsg() + "未传入保障集合或者未传入利益演示集合");
        }
        /* 校验年龄 */
        Pattern pattern = Pattern.compile(NUMBER_CHECK);
        if (!pattern.matcher(modifyRecommendationVO.getInsuredAge().toString()).matches()) {
            logger.info("传入年龄不为正整数");
            throw new BaseException(BaseErrorEnum.BODY_NOT_MATCH.getResultCode(), BaseErrorEnum.BODY_NOT_MATCH.getResultMsg() + ",传入年龄不为正整数");
        }
        Recommendation recommendation = new Recommendation();
        /* 使用工具直接进行实体与BO的复制转换，注意字段名及类型需保持一致 */
        BeanUtil.copyProperties(modifyRecommendationVO, recommendation);
        /* 设置基础数据 */
        setBaseData(recommendation);
        recommendationMapper.insert(recommendation);
        /* 向建议书附加险关联表插入记录 */
        List<RecommendationInsuranceMap> list = new ArrayList<>();
        /* 遍历险种集合转换类型并赋值 */
        for (AdditionalVO additionalVO : modifyRecommendationVO.getAdditionalVOList()) {
            RecommendationInsuranceMap recommendationInsuranceMap = new RecommendationInsuranceMap();
            BeanUtil.copyProperties(additionalVO, recommendationInsuranceMap);
            /* 设置基础数据 */
            setBaseData(recommendationInsuranceMap);
            /* 加入刚新增的建议书id */
            recommendationInsuranceMap.setRecommendationId(recommendation.getRecommendationId());
            list.add(recommendationInsuranceMap);
        }
        recommendationMapper.insertIntoMapBach(list);
        /* 向建议书附加险保障关联表插入记录 */
        if (!CollectionUtil.isEmpty(modifyRecommendationVO.getRecommendationSafeGuardInsuranceMapList())) {
            List<RecommendationSafeGuardInterestsMap> recommendationSafeGuardInterestsMapList = new ArrayList<>();
            /* 遍历险种集合转换类型并赋值 */
            for (RecommendationSafeGuardInterestsMapBO recommendationSafeGuardInterestsMapBO : modifyRecommendationVO.getRecommendationSafeGuardInsuranceMapList()) {
                for (RecommendationSafeGuardInterestsMapSubBO recommendationSafeGuardInterestsMapSubBO : recommendationSafeGuardInterestsMapBO.getRecommendationSafeGuardInterestsMapSubBOList()) {
                    /* 实例化一个对应关系对象 */
                    RecommendationSafeGuardInterestsMap recommendationSafeGuardInterestsMap = new RecommendationSafeGuardInterestsMap();
                    BeanUtil.copyProperties(recommendationSafeGuardInterestsMapBO, recommendationSafeGuardInterestsMap);
                    /* 设置基础数据 */
                    setBaseData(recommendationSafeGuardInterestsMap);
                    /* 设置子内容和内容 */
                    recommendationSafeGuardInterestsMap.setSafeGuardInterestsContent(recommendationSafeGuardInterestsMapSubBO.getSafeGuardInterestsContent());
                    recommendationSafeGuardInterestsMap.setSafeGuardInterestsSubContent(recommendationSafeGuardInterestsMapSubBO.getSafeGuardInterestsSubContent());
                    /* 设置刚新增的建议书id */
                    recommendationSafeGuardInterestsMap.setRecommendationId(recommendation.getRecommendationId());
                    /* 设置名目和详细内容 */
                    recommendationSafeGuardInterestsMap.setSafeGuardInterestsDetailedSubContent(recommendationSafeGuardInterestsMapBO.getSafeGuardInterestsDetailedSubContent());
                    recommendationSafeGuardInterestsMap.setSafeGuardInterestsTitle(recommendationSafeGuardInterestsMapBO.getSafeGuardInterestsTitle());
                    recommendationSafeGuardInterestsMapList.add(recommendationSafeGuardInterestsMap);
                }
            }
            recommendationSafeGuardInsuranceMapMapper.insertIntoMapBach(recommendationSafeGuardInterestsMapList);
        }
        /* 向建议书利益演示关联表插入记录,递归遍历实例化记录对象 */
        if (modifyRecommendationVO.getSafeGuardInterestsFormulaMapList() != null) {
            List<RecommendationSafeGuardInterestsFormulaMap> recommendationSafeGuardInterestsFormulaMapList = new ArrayList<>();
            for (Map.Entry<String, List<RecommendationSafeGuardInterestsFormulaMapBO>> stringListEntry : modifyRecommendationVO.getSafeGuardInterestsFormulaMapList().entrySet()) {
                for (RecommendationSafeGuardInterestsFormulaMapBO recommendationSafeGuardInterestsFormulaMapBO : stringListEntry.getValue()) {
                    RecommendationSafeGuardInterestsFormulaMap recommendationSafeGuardInterestsFormulaMap = new RecommendationSafeGuardInterestsFormulaMap();
                    /* 设置利益演示数据 */
                    BeanUtil.copyProperties(recommendationSafeGuardInterestsFormulaMapBO, recommendationSafeGuardInterestsFormulaMap);
                    /* 设置基础数据 */
                    setBaseData(recommendationSafeGuardInterestsFormulaMap);
                    /* 设置刚新增的建议书id */
                    recommendationSafeGuardInterestsFormulaMap.setRecommendationId(recommendation.getRecommendationId());
                    recommendationSafeGuardInterestsFormulaMapList.add(recommendationSafeGuardInterestsFormulaMap);
                }
            }
            recommendationSafeGuardInsuranceMapMapper.insertIntoFormulaMapBach(recommendationSafeGuardInterestsFormulaMapList);
        }
        return recommendation.getRecommendationId();
    }

    /**
     * (non-Javadoc)
     * <p>
     * com.newtouch.bxzs.business.product.service.RecommendationService#
     * makeRecommendation(com.newtouch.bxzs.business.product.model.
     * MakeRecommendationVO)
     */
    @Override
    public MakeRecommendationOnAppBO makeRecommendation(MakeRecommendationVO makeRecommendationVO) {
        /* 效验 */
        if (BeanUtil.isEmpty(makeRecommendationVO)) {
            logger.info("传入数据不符合条件");
            throw new BaseException(BaseErrorEnum.REQUEST_DATA_NULL);
        }
        /* 校验年龄 */
        Pattern pattern = Pattern.compile(NUMBER_CHECK);
        if (!pattern.matcher(makeRecommendationVO.getInsuredAge().toString()).matches()) {
            logger.info("传入年龄不为正整数");
            throw new BaseException(BaseErrorEnum.BODY_NOT_MATCH.getResultCode(), BaseErrorEnum.BODY_NOT_MATCH.getResultMsg() + ",传入年龄不为正整数");
        }
        /* 校验证件类型和证件号 */
        CheckCertificateTypeUtil.checkCertificate(makeRecommendationVO.getInsurederCertificateType(), makeRecommendationVO.getInsurederCertificateNum());
        Assert.isTrue(!BeanUtil.isEmpty(makeRecommendationVO.getInsuredAge()), "被保人年龄未填");
        Assert.isTrue(!BeanUtil.isEmpty(makeRecommendationVO.getInsuredAmount()), "主险保额未填");
        Assert.isTrue(!StringUtils.isEmpty(makeRecommendationVO.getInsurederName()), "被保人姓名未填");
        Assert.isTrue(!StringUtils.isEmpty(makeRecommendationVO.getInsuredSex()), "被保人性别未填");
        Assert.isTrue(!StringUtils.isEmpty(makeRecommendationVO.getPaymentMethod()), "缴费方式未填");
        Assert.isTrue(!StringUtils.isEmpty(makeRecommendationVO.getPaymentPeriod()), "缴费期间未填");
        Assert.isTrue(!StringUtils.isEmpty(makeRecommendationVO.getProductCode()), "产品编号未填");
        Assert.isTrue(!StringUtils.isEmpty(makeRecommendationVO.getProductId()), "产品id未填");
        Assert.isTrue(!StringUtils.isEmpty(makeRecommendationVO.getProductName()), "产品名称未填");
        Assert.isTrue(!BeanUtil.isEmpty(makeRecommendationVO.getReceivingAge()), "主险种领取年龄未填");
        Assert.isTrue(!StringUtils.isEmpty(makeRecommendationVO.getInsurederCertificateNum()), "被保人证件号未填");
        Assert.isTrue(!StringUtils.isEmpty(makeRecommendationVO.getInsurederCertificateType()), "被保人证件类型未填");
        /* 判断输入的客户信息是否在数据库存在，若存在，判断输入的信息是否有误 */
        QueryWrapper<Recommendation> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("INSUREDER_CERTIFICATE_NUMBER", makeRecommendationVO.getInsurederCertificateNum())
                .eq("INSUREDER_CERTIFICATE_TYPE", makeRecommendationVO.getInsurederCertificateType());
        RecommendationDetailBO recommendationDetailBO = new RecommendationDetailBO();
        List<Recommendation> list = recommendationMapper.selectList(queryWrapper);
        if(list.size()>0){
            BeanUtil.copyProperties(list.get(0), recommendationDetailBO);
            if (!BeanUtil.isEmpty(recommendationDetailBO) && !StringUtils.isEmpty(recommendationDetailBO.getInsurederCertificateType())
                    && !StringUtils.isEmpty(recommendationDetailBO.getInsurederCertificateNum())) {
                if (recommendationDetailBO.getInsurederCertificateType().equals(makeRecommendationVO.getInsurederCertificateType())
                        && recommendationDetailBO.getInsurederCertificateNum().equals(makeRecommendationVO.getInsurederCertificateNum())) {
                    if (!Objects.equals(makeRecommendationVO.getInsurederName(), recommendationDetailBO.getInsurederName())) {
                        logger.info("传入数据不符合条件");
                        throw new BaseException(BaseErrorEnum.REQUEST_PARAMETER_ERROR.getResultCode(), "已存在该客户的数据，但姓名不一致");
                    }
                    if (!Objects.equals(makeRecommendationVO.getInsuredSex(), recommendationDetailBO.getInsuredSex())) {
                        logger.info("传入数据不符合条件");
                        throw new BaseException(BaseErrorEnum.REQUEST_PARAMETER_ERROR.getResultCode(), "已存在该客户的数据，但性别不一致");
                    }
                }
            }
        }
        /* 获取模拟端数据 */
        MakeRecommendationBO makeRecommendationBO = productFeignClient.getRecommendation(makeRecommendationVO);
        MakeRecommendationOnAppBO makeRecommendationOnAppBO = new MakeRecommendationOnAppBO();
        /* 包装数据 */
        makeRecommendationOnAppBO.setProductEnclosureNameList(productService.getProductDetail(makeRecommendationVO.getProductId()).getProductEnclosureNameList());
        makeRecommendationOnAppBO.setMakeRecommendationBO(makeRecommendationBO);
        /* 计算首年保费 */
        BigDecimal firstYearTotal = new BigDecimal("0.00");
        if (!CollectionUtil.isEmpty(makeRecommendationBO.getInsuranceBOList())) {
            for (InsuranceBO bo : makeRecommendationBO.getInsuranceBOList()) {
                if (bo.getPolicyPremium() != null) {
                    firstYearTotal = firstYearTotal.add(bo.getPolicyPremium());
                }
            }
        }
        makeRecommendationOnAppBO.setFirstYearTotal(firstYearTotal);
        /*设置保障期限*/
        String policyPeriod;
        policyPeriod = makeRecommendationVO.getPolicyPeriod();
        if (POLICY_PERIOD.equals(makeRecommendationVO.getPolicyPeriod())) {
            policyPeriod = "100";
        }
        makeRecommendationOnAppBO.setPolicyPeriod(policyPeriod);
        return makeRecommendationOnAppBO;
    }

    /**
     * (non-Javadoc)
     * <p>
     * com.newtouch.bxzs.business.product.service.RecommendationService#
     * getPremiumCalculation(java.util.List)
     */
    @Override
    public List<PremiumTrialBO> getPremiumCalculation(List<PremiumTrialVO> premiumTrialVOList) {
        if (CollectionUtil.isEmpty(premiumTrialVOList)) {
            logger.info("传入保费试算集合为空");
            throw new BaseException(BaseErrorEnum.REQUEST_DATA_NULL);
        }
        for (PremiumTrialVO premiumTrialVO : premiumTrialVOList) {
            if (BeanUtil.isEmpty(premiumTrialVO.getPolicyAmount())) {
                logger.info("保额未填写");
                throw new BaseException(BaseErrorEnum.REQUIRED_ITEM_NULL.getResultCode(), BaseErrorEnum.REQUIRED_ITEM_NULL.getResultMsg() + ",保额未填写");
            }
            /* 校验保额 */
            Pattern pattern = Pattern.compile(NUMBER_CHECK);
            if (!pattern.matcher(premiumTrialVO.getPolicyAmount().toString()).matches()) {
                logger.info("传入保额存在不为正整数");
                throw new BaseException(BaseErrorEnum.BODY_NOT_MATCH.getResultCode(), BaseErrorEnum.BODY_NOT_MATCH.getResultMsg() + ",传入保额存在不为正整数");
            }
        }
        return productFeignClient.getPremiumCalculation(premiumTrialVOList);
    }

    /**
     * (non-Javadoc)
     * <p>
     * com.newtouch.bxzs.business.product.service.RecommendationService#
     * recommendProduct(com.newtouch.bxzs.business.product.model.ProductRecommendVO)
     */
    @Override
    public IPage<ProductOnAppBO> recommendProduct(ProductRecommendVO productRecommendVO) {
        //效验
        if (BeanUtil.isEmpty(productRecommendVO)) {
            logger.info("请求参数为空");
            throw new BaseException(BaseErrorEnum.REQUEST_DATA_NULL);
        }
        if (StringUtils.isEmpty(productRecommendVO.getCustomerCertificateNumber()) || StringUtils.isEmpty(productRecommendVO.getCustomerCertificateType()) ||
                StringUtils.isEmpty(productRecommendVO.getCustomerName())) {
            logger.info("必录项未填");
            throw new BaseException(BaseErrorEnum.REQUIRED_ITEM_NULL.getResultCode(), "请选择证件类型和填写证件号码");
        }
        //根据客户三要素获取客户标签
        CustomerAnalysisVO customerAnalysisVO = new CustomerAnalysisVO();
        BeanUtil.copyProperties(productRecommendVO, customerAnalysisVO);
        //从缓存里面判断本端是保险还是银行(保险是2，银行是1)
        int platform = Integer.parseInt(getParameterValueRedis(SystemParamsEnum.BANKING_OR_INSURANCE.getCode()));
        List<Integer> labels = new ArrayList<>();
        if (platform == 1) {
            //银行
            BankCustomerAnalysisBO bankCustomerAnalysisBO;
            SendHttpRequestUtils<CustomerAnalysisVO> sendHttpRequestUtils = new SendHttpRequestUtils<>();
            JSONObject jsonObject = sendHttpRequestUtils.sendHttpRequestToJson(customerAnalysisVO, redisUtils.get(SystemParamsEnum.INSURANCE_CUSTOMER_ANALYSIS_INFO.getCode()));
            if (jsonObject != null) {
                bankCustomerAnalysisBO = JSONObject.toJavaObject(jsonObject, BankCustomerAnalysisBO.class);
            } else {
                logger.error("暂无该客户分析信息");
                throw new BaseException(BaseErrorEnum.NO_CUSTOMER_ANALYSIS_INFORMATION);
            }
            if (!StringUtils.isEmpty(bankCustomerAnalysisBO.getCustomerLabel())) {
                for (String str : bankCustomerAnalysisBO.getCustomerLabel().split(",")) {
                    labels.add(Integer.parseInt(str));
                }
            }
        } else {
            //保险
            InsuranceCustomerAnalysisBO insuranceCustomerAnalysisBO;
            SendHttpRequestUtils<CustomerAnalysisVO> sendHttpRequestUtils = new SendHttpRequestUtils<>();
            JSONObject jsonObject = sendHttpRequestUtils.sendHttpRequestToJson(customerAnalysisVO, redisUtils.get(SystemParamsEnum.BANK_CUSTOMER_ANALYSIS_INFO.getCode()));
            if (jsonObject != null) {
                insuranceCustomerAnalysisBO = JSONObject.toJavaObject(jsonObject, InsuranceCustomerAnalysisBO.class);
            } else {
                logger.error("暂无该客户分析信息");
                throw new BaseException(BaseErrorEnum.NO_CUSTOMER_ANALYSIS_INFORMATION);
            }
            if (!StringUtils.isEmpty(insuranceCustomerAnalysisBO.getCustomerLabel())) {
                for (String str : insuranceCustomerAnalysisBO.getCustomerLabel().split(",")) {
                    labels.add(Integer.parseInt(str));
                }
            }
        }
        //如果标签不存在则返回其他
        if (labels.size() == 0) {
            labels.add(OTHER_LABEL);
        }
        //创建一个新的集合存放推荐产品
        IPage<ProductOnAppBO> page = new Page<>();
        //开始匹配
        ProductAppVO productAppVO = new ProductAppVO();
        BeanUtil.copyProperties(productRecommendVO, productAppVO);
        productAppVO.setPageSize(limit);
        productAppVO.setCurrentPage(currentPage);
        IPage<ProductOnAppBO> iPage = productService.getProductListOnApp(productAppVO);
        //如所有产品都未匹配成功则按产品选择界面的展示逻辑显示主推产品或热销产品,若有匹配成功的产品，则仅展示匹配成功的产品
        List<ProductRecommendOnAppBO> productRecommendList = new ArrayList<>();
        for (int i = 0; i < iPage.getRecords().size(); i++) {
            List<Integer> lists = new ArrayList<>();
            String[] strings = iPage.getRecords().get(i).getProductLabel().split(",");
            if (strings.length != 0) {
                for (String string : strings) {
                    lists.add(Integer.parseInt(string));
                }
            }
            int labelMatchingCount = 0;
            for (Integer label : labels) {
                for (Integer list : lists) {
                    if (Objects.equals(list, label)) {
                        labelMatchingCount++;
                    }
                }
            }
            //实例化带排序字段的产品类
            if (labelMatchingCount != 0) {
                ProductRecommendOnAppBO productRecommendOnAppBO = new ProductRecommendOnAppBO();
                BeanUtil.copyProperties(iPage.getRecords().get(i), productRecommendOnAppBO);
                productRecommendOnAppBO.setLabelMatchingCount(labelMatchingCount);
                productRecommendList.add(productRecommendOnAppBO);
            }
        }
        //排序
        Collections.sort(productRecommendList);
        List<ProductOnAppBO> list = new ArrayList<>();
        for (ProductRecommendOnAppBO productRecommendOnAppBO : productRecommendList) {
            ProductOnAppBO productOnAppBO = new ProductOnAppBO();
            BeanUtil.copyProperties(productRecommendOnAppBO, productOnAppBO);
            list.add(productOnAppBO);
        }
        if (CollectionUtils.isEmpty(productRecommendList)) {
            return productService.getProductListOnApp(productAppVO);
        }
        page.setRecords(list);
        return page;
    }

    @Override
    public Integer getRecommendationByRelationId(String relationId) {
        return recommendationMapper.getRecommendationByRelationId(relationId);
    }

    /**
     * 设置基础数据
     *
     * @param obj 需要设置基础数据的对象
     */
    private void setBaseData(Object obj) {
        BaseDataVO baseDataVO = new BaseDataVO();
        baseDataVO.setCreateTime(new Date());
        baseDataVO.setCreateUserId(Objects.requireNonNull(Objects.requireNonNull(UserDetailUtil.getUserDetail()).getUserId()));
        baseDataVO.setUpdateTime(new Date());
        baseDataVO.setUpdateUserId(Objects.requireNonNull(Objects.requireNonNull(UserDetailUtil.getUserDetail()).getUserId()));
        BeanUtil.copyProperties(baseDataVO, obj);
    }

    /**
     * 根据系统参数编码,获取缓存,如果为空更新缓存
     *
     * @param code 系统参数编码
     * @return 系统参数值
     */
    public String getParameterValueRedis(String code) {
        if (StringUtils.isEmpty(code)) {
            throw new BaseException(BaseErrorEnum.REQUEST_DATA_NULL);
        }
        String systemParameterValue = redisUtils.get(code);
        //如果值为空，更新缓存
        if (StringUtils.isEmpty(systemParameterValue)) {
            QueryWrapper<SystemParameter> query = new QueryWrapper<>();
            query.eq("SYSTEM_PARAMETER_CODE", code);
            query.eq("IS_ENABLE", true);
            SystemParameter systemParameter = sysParameterMapper.selectOne(query);
            systemParameterValue = systemParameter.getSystemParameterValue();
            if (StringUtils.isEmpty(systemParameterValue)) {
                throw new BaseException(BaseErrorEnum.NOT_FOUND);
            }
            //更新缓存
            redisUtils.getAndSet(code, systemParameterValue);
        }
        return systemParameterValue;
    }

}
